/*
 * Copyright (c) 2022, IMMORTA Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice, this
 *   list of conditions and the following disclaimer in the documentation and/or
 *   other materials provided with the distribution.
 *
 * - Neither the name of IMMORTA Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef HSM_DRV_H
#define HSM_DRV_H

/*!
 * @file hsm_drv.h
 * @brief This file declares hsm driver interfaces
 */

/*!
 * @addtogroup hsm_drv
 * @{
 */

/*******Includes***************************************************************/
#include <stdbool.h>
#include "Os_Adapter.h"

/*******Definitions************************************************************/
/*!
 * @brief Specify HSM life cycle
 */
typedef enum {
    LIFE_CYCLE_TEST_MODE         = 0x01U,
    LIFE_CYCLE_DEVELOP_MODE      = 0x02U,
    LIFE_CYCLE_MANUFACTURE_MODE  = 0x03U,
    LIFE_CYCLE_USER_MODE         = 0x04U,
    LIFE_CYCLE_DEBUG_MODE        = 0x05U,
    LIFE_CYCLE_DESTROY_MODE      = 0x06U,
    LIFE_CYCLE_UNDEF_MODE        = 0x07U
} life_cycle_t;

/*!
 * @brief Specify status content of the SHE status register
 */
#define HSM_STATUS_BUSY               (0x001U)
#define HSM_STATUS_SECURE_BOOT        (0x002U)
#define HSM_STATUS_BOOT_INIT          (0x004U)
#define HSM_STATUS_BOOT_FINISHED      (0x008U)
#define HSM_STATUS_BOOT_OK            (0x010U)
#define HSM_STATUS_RND_INT            (0x020U)
#define HSM_STATUS_EXT_DEBUGGER       (0x040U)
#define HSM_STATUS_INT_DEBUGGER       (0x080U)

/*!
 * @brief Specify HSM firmware information
 */
typedef struct {
    bool fwDone;           /*!< HSM FW boot done status */
    bool fwError;          /*!< HSM FW boot error status */
    uint32_t fwVersion;    /*!< HSM FW version number. if hsm fw boot fail, fwVersion is 0 */
} hsm_fw_info_t;

/*!
 * @brief Specify the KeyID to be used to implement the requested cryptographic operation
 */
typedef enum {
    HSM_SECRET_KEY     = 0x00U,
    HSM_MASTER_ECU_KEY = 0x01U,
    HSM_BOOT_MAC_KEY   = 0x02U,
    HSM_BOOT_MAC       = 0x03U,
    HSM_KEY_1          = 0x04U,
    HSM_KEY_2          = 0x05U,
    HSM_KEY_3          = 0x06U,
    HSM_KEY_4          = 0x07U,
    HSM_KEY_5          = 0x08U,
    HSM_KEY_6          = 0x09U,
    HSM_KEY_7          = 0x0AU,
    HSM_KEY_8          = 0x0BU,
    HSM_KEY_9          = 0x0CU,
    HSM_KEY_10         = 0x0DU,
    HSM_RAM_KEY        = 0x0EU,
    HSM_KEY_11         = 0x14U,
    HSM_KEY_12         = 0x15U,
    HSM_KEY_13         = 0x16U,
    HSM_KEY_14         = 0x17U,
    HSM_KEY_15         = 0x18U,
    HSM_KEY_16         = 0x19U,
    HSM_KEY_17         = 0x1AU,
    HSM_KEY_18         = 0x1BU,
    HSM_KEY_19         = 0x1CU,
    HSM_KEY_20         = 0x1DU,
    HSM_KEY_21         = 0x24U,
    HSM_KEY_22         = 0x25U,
    HSM_KEY_23         = 0x26U,
    HSM_KEY_24         = 0x27U,
    HSM_KEY_25         = 0x28U,
    HSM_KEY_26         = 0x29U,
    HSM_KEY_27         = 0x2AU,
    HSM_KEY_28         = 0x2BU,
    HSM_KEY_29         = 0x2CU,
    HSM_KEY_30         = 0x2DU,
    HSM_SOC_DEBUG_KEY  = 0x2FU
} hsm_key_id_t;

/*!
 * @brief HSM commands which follow the same values as the SHE command definition, includes extended commands
 */
typedef enum {
    HSM_CMD_ENC_ECB = 0x1U,
    HSM_CMD_ENC_CBC,
    HSM_CMD_DEC_ECB,
    HSM_CMD_DEC_CBC,
    HSM_CMD_GENERATE_MAC,
    HSM_CMD_VERIFY_MAC,
    HSM_CMD_LOAD_KEY,
    HSM_CMD_LOAD_KEY_EXTEND,
    HSM_CMD_LOAD_PLAIN_KEY,
    HSM_CMD_LOAD_PLAIN_KEY_EXTEND,
    HSM_CMD_EXPORT_RAM_KEY,
    HSM_CMD_EXPORT_RAM_KEY_EXTEND,
    HSM_CMD_INIT_RNG,
    HSM_CMD_RESERVED_1,
    HSM_CMD_RND,
    HSM_CMD_RESERVED_2,
    HSM_CMD_BOOT_FAILURE,
    HSM_CMD_BOOT_OK,
    HSM_CMD_GET_STATUS,
    HSM_CMD_GET_ID,
    HSM_CMD_BOOT_DEFINE,
    HSM_CMD_RESERVED_3,
    HSM_CMD_RESERVED_4,
    HSM_CMD_MP_COMPRESS,
    HSM_CMD_DBG_CHAL,
    HSM_CMD_DBG_AUTH,
    HSM_CMD_DBG_IF_CHAL,
    HSM_CMD_DBG_IF_AUTH,
    HSM_CMD_SET_LIFE_CYCLE,
    HSM_CMD_GENERATE_HASH,
    HSM_CMD_VERIFY_SIGN
} hsm_cmd_t;

/*!
 * @brief Specifies cryptographic algorithm
 */
typedef enum {
    CRYPTO_ALG_AES128 = 0x01U,
    CRYPTO_ALG_AES256 = 0x02U,
    CRYPTO_ALG_SM4    = 0x03U
} crypto_alg_t;

/*!
 * @brief Specifies the boot type for the BOOT_DEFINE command
 */
typedef enum {
    HSM_BOOT_STRICT_SERIAL       = 0x01U,
    HSM_BOOT_SERIAL              = 0x02U,
    HSM_BOOT_PARALLEL            = 0x03U,
    HSM_BOOT_NOT_DEFINED         = 0xFFU
} hsm_boot_type_t;

/*!
 * @brief Debug authentication type
 */
typedef enum {
    AUTH_TYPE_SOC_DEBUG  =  0x01U,
    AUTH_TYPE_HSM_DEBUG  =  0x02U
} dbg_auth_type_t;

/*!
 * @brief Process mode
 */
typedef enum {
    PROCESS_MODE_START       = 1U,
    PROCESS_MODE_UPDATE      = 2U,
    PROCESS_MODE_FINISH      = 3U,
    PROCESS_MODE_ONEPASS     = 4U
} hsm_process_mode_type_t;

/*!
 * @brief Hash algorithm definition
 */
typedef enum {
    HASH_SHA256             = 1U,
    HASH_SHA384             = 2U,
    HASH_SHA512             = 3U,
    HASH_SHA224             = 4U,
    HASH_SHA512_224         = 5U,
    HASH_SHA512_256         = 6U
} hash_alg_type_t;

/*!
 * @brief Rsa public key
 */
typedef struct {
    uint32_t nBits;               /*!< bit length of Public Modulus (n), support 2048/3072/4096 */
    const uint8_t* n;             /*!< Public Modulus */
    uint32_t eBits;               /*!< bit length of Public Exponent (e) */
    const uint8_t* e;             /*!< Public Exponent */
} rsa_public_key_type_t;

/*!
 * @brief Callback for HSM interrupt
 */
typedef void (*mailbox_callback_t)(uint32_t completedCmd, void* callbackParam);

/*!
 * @brief Internal driver state information
 */
typedef struct {
    bool cmdInProgress;            /*!< Specifies if a command is in progress */
    hsm_cmd_t cmd;                 /*!< Specifies the type of the command in execution */
    semaphore_t cmdSemaphore;      /*!< Semaphore used by blocking functions */
    mailbox_callback_t callback;   /*!< The callback invoked when an asynchronous command is completed */
    void* callbackParam;           /*!< User parameter for the command completion callback */
} hsm_state_t;

/*******APIs*******************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif

/*!
 * @brief Initializes the internal state of the driver and enables the MBOX interrupt
 *
 * @param[in] state: Pointer to the state structure which will be used for
 *                   holding the internal state of the driver
 * @return None
 */
errcode_t HSM_Init(hsm_state_t* state);

/*!
 * @brief Clears the internal state of the driver and disables the MBOX interrupt
 * @param[in] None
 * @return None
 */
void HSM_DeInit(void);

/*!
 * @brief This function updates an internal key per the SHE specification,
 *        It was standard to support 128bits
 *
 * @param[in] keyId: KeyID of the key to be updated
 * @param[in] m1: Pointer to the 128-bit M1 message containing the UID, Key ID
 *            and Authentication Key ID
 * @param[in] m2: Pointer to the 256-bit M2 message contains the new security
 *            flags, counter and the key value all encrypted using a derived key generated
 *            from the Authentication Key
 * @param[in] m3: Pointer to the 128-bit M3 message is a MAC generated over messages M1 and M2
 * @param[out] m4: Pointer to a 256 bits buffer where the computed M4 parameter is stored
 * @param[out] m5: Pointer to a 128 bits buffer where the computed M5 parameters is stored
 * @return Error Code after command execution
 *         Output parameters are valid if the error code is ERR_SUCCESS
 */
errcode_t HSM_LoadKey(hsm_key_id_t keyId,
                      const uint8_t* m1,
                      const uint8_t* m2,
                      const uint8_t* m3,
                      uint8_t* m4,
                      uint8_t* m5);

/*!
 * @brief Updates an internal key per the SHE specification,
 *        It was extended to support 256bits
 *
 * @param[in] keyId: KeyID of the key to be updated
 * @param[in] m1: Pointer to the 128-bit M1 message containing the UID, Key ID
 *            and Authentication Key ID
 * @param[in] m2: Pointer to the 256+128(extend) bits M2 message contains the new security
 *            flags, counter and the key value all encrypted using a derived key generated
 *            from the Authentication Key
 * @param[in] m3: Pointer to the 128-bit M3 message is a MAC generated over messages M1 and M2
 * @param[out] m4: Pointer to a 256 bits buffer where the computed M4 parameter is stored
 * @param[out] m5: Pointer to a 128 bits buffer where the computed M5 parameters is stored
 * @return Error Code after command execution
 *         Output parameters are valid if the error code is ERR_SUCCESS
 */
errcode_t HSM_LoadKeyExtend(hsm_key_id_t keyId,
                            const uint8_t* m1,
                            const uint8_t* m2,
                            const uint8_t* m3,
                            uint8_t* m4,
                            uint8_t* m5);

/*!
 * @brief Updates the RAM key memory slot with a 128-bit plaintext,
 *        It was standard to support 128bits
 *
 * @param[in] plainKey: Pointer to the 128-bit buffer,
 *            containing the key that needs to be copied in RAM_KEY slot
 * @return Error Code after command execution
 */
errcode_t HSM_LoadPlainKey(const uint8_t* plainKey);

/*!
 * @brief Updates the RAM key memory slot with a 256-bit plaintext,
 *        It was extended to support 256bits
 *
 * @param[in] plainKey: Pointer to the 256-bit buffer,
 *            containing the key that needs to be copied in RAM_KEY slot
 * @return Error Code after command execution
 */
errcode_t HSM_LoadPlainKeyExtend(const uint8_t* plainKey);

/*!
 * @brief Exports the RAM_KEY into a format protected by SECRET_KEY,
 *        It was standard to support 128bits
 *
 * @param[out] m1: Pointer to a buffer where the M1 parameter will be exported
 * @param[out] m2: Pointer to a buffer where the M2 parameter will be exported
 * @param[out] m3: Pointer to a buffer where the M3 parameter will be exported
 * @param[out] m4: Pointer to a buffer where the M4 parameter will be exported
 * @param[out] m5: Pointer to a buffer where the M5 parameter will be exported
 * @return Error Code after command execution
 *         Output parameters are valid if the error code is ERR_SUCCESS
 */
errcode_t HSM_ExportRAMKey(uint8_t* m1, uint8_t* m2, uint8_t* m3,
                           uint8_t* m4, uint8_t* m5);

/*!
 * @brief Exports the RAM_KEY into a format protected by SECRET_KEY,
 *        It was extended to support 256bits
 *
 * @param[out] m1: Pointer to a buffer where the M1 parameter will be exported
 * @param[out] m2: Pointer to a buffer where the M2 parameter will be exported
 * @param[out] m3: Pointer to a buffer where the M3 parameter will be exported
 * @param[out] m4: Pointer to a buffer where the M4 parameter will be exported
 * @param[out] m5: Pointer to a buffer where the M5 parameter will be exported
 * @return Error Code after command execution
 *         Output parameters are valid if the error code is ERR_SUCCESS
 */
errcode_t HSM_ExportRAMKeyExtend(uint8_t* m1, uint8_t* m2, uint8_t* m3,
                                 uint8_t* m4, uint8_t* m5);

/*!
 * @brief This function performs the AES-128/AES-256/SM4 encryption
 *        in ECB mode of the input plain text buffer
 *
 * @param[in] alg: algorithm select,AES-128/AES-256/SM4
 * @param[in] keyId: KeyID used to perform the cryptographic operation
 * @param[in] plainText: Pointer to the plain text buffer
 * @param[in] length: Number of bytes of plain text message to be encrypted
 *            It should be multiple of 16 bytes
 * @param[out] cipherText: Pointer to the cipher text buffer. The buffer shall
 *             have the same size as the plain text buffer
 * @param[in] timeout: Timeout in milliseconds
 * @return Error Code after command execution
 *         Output parameters are valid ifthe error code is ERR_SUCCESS
 */
errcode_t HSM_EncryptECB(crypto_alg_t alg,
                         hsm_key_id_t keyId,
                         const uint8_t* plainText,
                         uint32_t length,
                         uint8_t* cipherText,
                         uint32_t timeout);

/*!
 * @brief This function performs the AES-128/AES-256/SM4 decryption
 *        in ECB mode of the input cipher text buffer
 *
 * @param[in] alg: algorithm select,AES-128/AES-256/SM4
 * @param[in] keyId: KeyID used to perform the cryptographic operation
 * @param[in] cipherText: Pointer to the cipher text buffer
 * @param[in] length: Number of bytes of cipher text message to be decrypted
 *            It should be multiple of 16 bytes
 * @param[out] plainText: Pointer to the plain text buffer. The buffer shall
 *             have the same size as the cipher text buffer
 * @param[in] timeout: Timeout in milliseconds
 * @return Error Code after command execution
 *               Output parameters are valid if the error code is ERR_SUCCESS
 */
errcode_t HSM_DecryptECB(crypto_alg_t alg,
                         hsm_key_id_t keyId,
                         const uint8_t* cipherText,
                         uint32_t length,
                         uint8_t* plainText,
                         uint32_t timeout);

/*!
 * @brief This function performs the AES-128/AES-256/SM4 encryption
 *        in CBC mode of the input plain text buffer
 *
 * @param[in] alg: algorithm select,AES-128/AES-256/SM4
 * @param[in] keyId: KeyID used to perform the cryptographic operation
 * @param[in] plainText: Pointer to the plain text buffer
 * @param[in] length: Number of bytes of plain text message to be encrypted
 *            It should be multiple of 16 bytes
 * @param[in] iv: Pointer to the initialization vector buffer
 * @param[out] cipherText: Pointer to the cipher text buffer. The buffer shall
 *             have the same size as the plain text buffer
 * @param[in] timeout: Timeout in milliseconds
 * @return Error Code after command execution
 *         Output parameters are valid ifthe error code is ERR_SUCCESS
 */
errcode_t HSM_EncryptCBC(crypto_alg_t alg,
                         hsm_key_id_t keyId,
                         const uint8_t* plainText,
                         uint32_t length,
                         const uint8_t* iv,
                         uint8_t* cipherText,
                         uint32_t timeout);

/*!
 * @brief This function performs the AES-128/AES-256/SM4 decryption
 *        in CBC mode of the input cipher text buffer
 *
 * @param[in] alg: algorithm select,AES-128/AES-256/SM4
 * @param[in] keyId: KeyID used to perform the cryptographic operation
 * @param[in] cipherText: Pointer to the cipher text buffer
 * @param[in] length: Number of bytes of cipher text message to be decrypted
 *            It should be multiple of 16 bytes
 * @param[in] iv: Pointer to the initialization vector buffer
 * @param[out] plainText: Pointer to the plain text buffer. The buffer shall
 *             have the same size as the cipher text buffer
 * @param[in] timeout: Timeout in milliseconds
 * @return Error Code after command execution
 *         Output parameters are valid if the error code is ERR_SUCCESS
 */
errcode_t HSM_DecryptCBC(crypto_alg_t alg,
                         hsm_key_id_t keyId,
                         const uint8_t* cipherText,
                         uint32_t length,
                         const uint8_t* iv,
                         uint8_t* plainText,
                         uint32_t timeout);

/*!
 * @brief This function calculates the MAC of a given message
 *        using CMAC with AES-128/AES-256/SM4
 *
 * @param[in] alg: algorithm select,AES-128/AES-256/SM4
 * @param[in] keyId: KeyID used to perform the cryptographic operation
 * @param[in] msg: Pointer to the message buffer
 * @param[in] msgLen: Number of byte of message on which CMAC will be computed,
 *            It should be multiple of 16 bytes
 * @param[out] cmac: Pointer to the buffer containing the result of the CMAC computation
 * @param[in] timeout: Timeout in milliseconds
 * @return Error Code after command execution
 *         Output parameters are valid if the error code is ERR_SUCCESS
 */
errcode_t HSM_GenerateMAC(crypto_alg_t alg,
                          hsm_key_id_t keyId,
                          const uint8_t* msg,
                          uint32_t msgLen,
                          uint8_t* cmac,
                          uint32_t timeout);

/*!
 * @brief This function verifies the MAC of a given message
 *        using CMAC with AES-128/AES-256/SM4
 *
 * @param[in] alg: algorithm select,AES-128/AES-256/SM4
 * @param[in] keyId: KeyID used to perform the cryptographic operation
 * @param[in] msg: Pointer to the message buffer
 * @param[in] msgLen: Number of bits of message on which CMAC will be computed
 * @param[in] mac: Pointer to the buffer containing the CMAC to be verified
 * @param[in] macLen: Number of byte of the CMAC to be compared
 * @param[out] verifyStatus: Status of MAC verification command
 *             (true:verification operation passed, false: verification operation failed)
 * @param[in] timeout: Timeout in milliseconds
 * @return Error Code after command execution
 *         Output parameters are valid if the error code is ERR_SUCCESS
 */
errcode_t HSM_VerifyMAC(crypto_alg_t alg,
                        hsm_key_id_t keyId,
                        const uint8_t* msg,
                        uint32_t msgLen,
                        const uint8_t* mac,
                        uint8_t macLen,
                        bool* verifyStatus,
                        uint32_t timeout);

/*!
 * @brief Set random enable or disable
 *
 * @param[in] enable: true or false
 * @return Error Code after command execution
 */
errcode_t HSM_EnableRND(bool enable);

/*!
 * @brief Generates up to 256 random bits
 *
 * @param[out] rnd: Pointer to buffer
 *                  where the generated random number has to be stored
 * @param[in] len: Number of bytes,the maximum value is 32
 * @return Error Code after command execution
 *         Output parameters are valid if the error code is ERR_SUCCESS
 */
errcode_t HSM_GenerateRND(uint8_t* rnd, uint32_t len);

/*!
 * @brief This function returns the identity (UID) and the value of the status register
 *        protected by a MAC over a challenge and the data
 *
 * @param[in] challenge: Pointer to the 128-bit buffer containing Challenge data.
 * @param[out] uid: Pointer to 120 bit buffer where the UID will be stored.
 * @param[out] sreg: Value of the status register.
 * @param[out] mac: Pointer to the 128 bit buffer where the MAC generated over
 *             challenge and UID and status  will be stored
 * @return Error Code after command execution
 *         Output parameters are valid if the error code is ERR_SUCCESS
 */
errcode_t HSM_GetID(const uint8_t* challenge,
                    uint8_t* uid,
                    uint8_t* sreg,
                    uint8_t* mac);

/*!
 * @brief This function set to compress the given messages
 *
 * @param[in] msg: Pointer to the messages to be compressed. Messages must be
 *            pre-processed per SHE specification if they do not already meet the full
 *            128-bit block size requirement
 * @param[in] msgLen: The number of bytes messages to be compressed.
 * @param[out] mpCompress: Pointer to the 128 bit buffer storing the compressed data
 * @param[in] timeout: Timeout in milliseconds
 * @return Error Code after command execution
 *         Output parameters are valid if the error code is ERR_SUCCESS.
 */
errcode_t HSM_MPCompress(const uint8_t* msg,
                         uint16_t msgLen,
                         uint8_t* mpCompress,
                         uint32_t timeout);

/*!
 * @brief Implements an extension of the SHE standard to define both the user
 *        boot size and boot method
 *
 * @param[in] alg: algorithm select,AES-128/AES-256/SM4
 * @param[in] bootSize: Number of blocks of 128-bit data to check on boot
 * @param[in] bootType: The boot method
 * @return Error Code after command execution
 */
errcode_t HSM_BootDefine(crypto_alg_t alg,
                         uint32_t bootSize,
                         hsm_boot_type_t bootType);

/*!
 * @brief The function is called during later stages of the boot process to detect a failure
 *
 * @param[in] None
 * @return Error Code after command execution
 */
errcode_t HSM_BootFailure(void);

/*!
 * @brief The function is called during later stages of the boot process to mark
 *        successful boot verification
 *
 * @param[in] None
 * @return Error Code after command execution
 */
errcode_t HSM_BootOK(void);

/*!
 * @brief This function obtains a random number which the user shall use along with the
 *        MASTER_ECU_KEY and UID to return an authorization request
 *
 * @param[out] challenge: Pointer to the 128-bits buffer
 *             where the challenge data will be stored
 * @return Error Code after command execution
 *         Output parameters are valid if the error code is ERR_SUCCESS
 */
errcode_t HSM_DbgChal(uint8_t* challenge);

/*!
 * @brief This function erases all keys (actual and outdated) stored in NVM Memory if
 *        the authorization is confirmed by HSM
 *
 * @param[in] authorization: Pointer to the 128-bits buffer containing the authorization value
 * @return Error Code after command execution
 */
errcode_t HSM_DbgAuth(const uint8_t* authorization);

/*!
 * @brief The function shall return the content of the status register
 *
 * @param[in] None
 * @return Value of the status register
 */
uint8_t HSM_GetStatus(void);

/*!
 * @brief The function shall return HSM firmware boot status and version counter
 *
 * @param[out] fw: Point to the firmware information struct
 * @return None
 */
void HSM_GetHsmFwInfo(hsm_fw_info_t* fw);

/*!
 * @brief The function shall return HSM whether to enter wfi
 *
 * @param[in] None
 * @return  hsm enter wfi status:
 *          - true: hsm enter wfi complete
 *          - false: hsm not enter wfi
 */
bool HSM_GetHsmEnterWfiStatus(void);

/*!
 * @brief The function shall Set life cycle of the chip
 *
 * @param[in] lc: life cycle
 * @return  Error Code after command execution
 */
errcode_t HSM_SetLifeCycle(life_cycle_t lc);

/*!
 * @brief The function shall return life cycle of the chip
 *
 * @param[in] None
 * @return The life cycle of the chip
 */
life_cycle_t HSM_GetLifeCycle(void);

/*!
 * @brief The function shall return HSM/SOC debug interface permission state
 *
 * @param[in] type: debug type, hsm debug or soc debug
 * @return  debug permission status:
 *          - true: allow access debug interface
 *          - false: not allow access debug interface
 */
bool HSM_DbgIfAccessIsAllowed(dbg_auth_type_t type);

/*!
 * @brief This function obtains a random number(256bits) and UID(120bits)
 *        which the user shall use along with the SOC_DEBUG_KEY/HSM_DEBUG_KEY
 *        return an authorization request
 *
 * @param[out] challenge: Pointer to the (256+120)-bits buffer
 *             where the challenge data will be stored
 * @return Error Code after command execution
 *         Output parameters are valid if the error code is ERR_SUCCESS
 */
errcode_t HSM_DbgIfChal(uint8_t* challenge);

/*!
 * @brief This function enable the debug interface if the authorization is confirmed by HSM
 *
 * @param[in] type: debug type, hsm debug or soc debug
 * @param[in] alg: algorithm select,AES-128/AES-256/SM4
 * @param[in] authorization: Pointer to the 128-bits buffer containing the authorization value
 * @return Error Code after command execution
 */
errcode_t HSM_DbgIfAuth(dbg_auth_type_t type,
                        crypto_alg_t alg,
                        const uint8_t* authorization);

/*!
 * @brief Mailbox interrupt handler process
 *
 * @param[in] None
 * @return None
 */
void MBOX_IRQHandlerProcess(void);


/*!
 * @brief This function calculates the hash digest in one pass mode
 *
 * @param[in] hashAlg: Hash algorithm select
 * @param[in] msg: Pointer to the message buffer
 * @param[in] msgLen: Number of byte of message on which hash will be computed
 * @param[out] digestOut: Pointer to the buffer containing the result of the hash computation
 * @param[in] timeout: Timeout in milliseconds
 * @return Error Code after command execution
 *         Output parameters are valid if the error code is ERR_SUCCESS
 */
errcode_t HSM_GenerateHashOnePass(hash_alg_type_t hashAlg,
                                  const uint8_t* msg,
                                  uint32_t msgLen,
                                  uint8_t* digestOut,
                                  uint32_t timeout);

/*!
 * @brief This function calculates the hash digest in start mode
 *
 * @param[in] hashAlg: Hash algorithm select
 * @param[in] ctxBuf: Pointer to the buffer that stores the context of the process
 * @param[in] ctxBufLen: Number of byte of the buffer that stores the context of the process
 *                       if hashAlg = SHA512/SHA384/SHA512_224/SHA512_256, CtxBufLen must be >= 328bytes
 *                       if hashAlg = SHA256/SHA224, CtxBufLen must be >= 168bytes
 * @param[in] timeout: Timeout in milliseconds
 * @return Error Code after command execution
 */
errcode_t HSM_GenerateHashStart(hash_alg_type_t hashAlg,
                                uint8_t* ctxBuf,
                                uint32_t ctxBufLen,
                                uint32_t timeout);

/*!
 * @brief This function calculates the hash digest in update mode
 *
 * @param[in] hashAlg: Hash algorithm select
 * @param[in] msg: Pointer to the message buffer
 * @param[in] msgLen: Number of byte of message on which hash will be computed
 * @param[in] ctxBuf: Pointer to the buffer that stores the context of the process
 * @param[in] ctxBufLen: Number of byte of the buffer that stores the context of the process
 *                       if hashAlg = SHA512/SHA384/SHA512_224/SHA512_256, CtxBufLen must be >= 328bytes
 *                       if hashAlg = SHA256/SHA224, CtxBufLen must be >= 168bytes
 * @param[in] timeout: Timeout in milliseconds
 * @return Error Code after command execution
 */
errcode_t HSM_GenerateHashUpdate(hash_alg_type_t hashAlg,
                                 const uint8_t* msg,
                                 uint32_t msgLen,
                                 uint8_t* ctxBuf,
                                 uint32_t ctxBufLen,
                                 uint32_t timeout);

/*!
 * @brief This function calculates the hash digest in finish mode
 *
 * @param[in] hashAlg: Hash algorithm select
 * @param[out] digestOut: Pointer to the buffer containing the result of the hash computation
 * @param[in] ctxBuf: Pointer to the buffer that stores the context of the process
 * @param[in] ctxBufLen: Number of byte of the buffer that stores the context of the process
 *                       if hashAlg = SHA512/SHA384/SHA512_224/SHA512_256, CtxBufLen must be >= 328bytes
 *                       if hashAlg = SHA256/SHA224, CtxBufLen must be >= 168bytes
 * @param[in] timeout: Timeout in milliseconds
 * @return Error Code after command execution
 *         Output parameters are valid if the error code is ERR_SUCCESS
 */
errcode_t HSM_GenerateHashFinish(hash_alg_type_t hashAlg,
                                 uint8_t* digestOut,
                                 uint8_t* ctxBuf,
                                 uint32_t ctxBufLen,
                                 uint32_t timeout);

/*!
 * @brief This function verification signature in RSA-PASS mode
 *
 * @param[in] hashAlg: Hash algorithm select
 * @param[in] saltLen: Number of byte of salt, if salt length is not known, set it to 0xFFFFFFFF,
 *                     The hsm will automatically recognizes the salt length
 * @param[in] digest: Pointer to the hash digest buffer, the digest is to be verified
 * @param[in] signature: Pointer to the RSA signature buffer, the signature is to be verified
 * @param[in] publicKey: Pointer to the public key buffer
 * @param[in] ctxBuf: Pointer to the buffer that stores the context of the process
 * @param[in] ctxBufLen: Number of byte of the buffer that stores the context of the process
 *                       CtxBufLen must be >= 4096bytes
 * @param[in] timeout: Timeout in milliseconds
 * @return Error Code after command execution
 *         if the error code is ERR_SUCCESS, indicates signature verify is pass
 */
errcode_t HSM_RsaPssVerifySign(hash_alg_type_t hashAlg,
                               uint32_t saltLen,
                               const uint8_t* digest,
                               const uint8_t* signature,
                               const rsa_public_key_type_t* publicKey,
                               uint8_t* ctxBuf,
                               uint32_t ctxBufLen,
                               uint32_t timeout);

#if defined(__cplusplus)
}
#endif

/*! @} */

#endif /* HSM_DRV_H */

/*******EOF********************************************************************/
